import re
import time
import threading
import datetime
from control.order_control import OrderType
from utils.e_mail import sendMail
from worker.base.base_worker import BaseWorker
from utils.log_util import prints
from utils.time_util import local_stamp_2_gmt, stamp2datetime
from constant.globl_constant import strategyList
from utils.time_util import stamp2datetime


class SimpleWorker(BaseWorker):
    """
    日内单边策略
    基于爬虫数据
    """

    lastDay = -1
    moveSpace = 3  # 盈利
    moveProfit = 1  # 移动间距

    buyAndSell = False  # 双边或单边挂单
    loginState = None
    orderTag = "挂单"

    def __init__(self):
        super().__init__()

    def startThread(self):
        """
        开启交易线程
        """
        thread = threading.Thread(target=self.articleTrade)
        # thread.daemon = True  # 设置线程为守护线程，以便在主程序退出时自动结束线程
        thread.start()

    def articleTrade(self):
        """
        文章策略交易
        """

        while True:
            if self.isLogin and self.marketClose() is False:
                currentPrice = self.control.getCurrentPrice(symbol=self.symble)
                buyPrice, sellPrice, coreStrategy = self.articlePrice()

                if self.buyAndSell and buyPrice != 0 and sellPrice != 0 and currentPrice > buyPrice + 2 and currentPrice < sellPrice - 2:
                    self.hangupOrder(1)
                    self.hangupOrder(2)
                else:
                    if coreStrategy == "buy" and buyPrice != 0 and currentPrice > buyPrice + 2:
                        self.hangupOrder(1)
                    elif coreStrategy == "sell" and sellPrice != 0 and currentPrice < sellPrice - 2:
                        self.hangupOrder(2)

                self.deleteLastDayOrder()
                self.extent(log=False)
                self.move2Profit()
            time.sleep(1)

    def hangupOrder(self, orderState):
        """
        挂单逻辑
        """
        # 持仓所有订单
        positionOrder = [
            item for item in self.getPositionsDetail(self.symble)
            if self.orderTag in item.comment
        ]
        # 日内所有订单
        inDayOrder = [
            item for item in self.dayAllOrder()
            if self.orderTag in item["comment"]
        ]
        # 所有挂单
        allOrder = self.getLimitOrderDetail(symbol=self.symble)
        buyOrder = [item for item in allOrder if item.type == 2]
        sellOrder = [item for item in allOrder if item.type == 3]

        timeHour = datetime.datetime.now().hour
        buyPrice, sellPrice, coreStrategy = self.articlePrice()

        if orderState == 1:
            # 单边挂单时，保持单边挂单状态
            if self.buyAndSell == False:
                self.strategyChangeForRemoveOrder("sell")
            if len(buyOrder) != 0:
                buyOpenPrice = buyOrder[0].price_open
                if buyPrice + 1 != buyOpenPrice:
                    # 是否存在该挂单，存在的话就修改，不存在的话则为已成交
                    self.changeLimitOrder(buyOpenPrice, buyPrice + 2,
                                          self.ORDER_TYPE_BUY_LIMIT)
            elif len(inDayOrder) == 0 and len(positionOrder) == 0:
                self.sendLimitOrder(buyPrice + 2, sellPrice,
                                    self.ORDER_TYPE_BUY_LIMIT)
            # 6点以前有挂单盈利单，继续挂单
            elif len(inDayOrder) != 0 and len(positionOrder) == 0:
                limitHour = stamp2datetime(inDayOrder[-1]["end_time"]).hour
                limitProfit = inDayOrder[-1]["profit"]
                if limitProfit > 0 and limitHour < 6 and timeHour > 6:
                    self.sendLimitOrder(buyPrice + 2, sellPrice,
                                        self.ORDER_TYPE_BUY_LIMIT)
        elif orderState == 2:
            # 单边挂单时，保持单边挂单状态
            if self.buyAndSell == False:
                self.strategyChangeForRemoveOrder("buy")
            if len(sellOrder) != 0:
                sellOpenPrice = sellOrder[0].price_open
                if sellPrice - 1 != sellOpenPrice:
                    # 是否存在该挂单，存在的话就修改，不存在的话则为已成交
                    self.changeLimitOrder(sellOpenPrice, sellPrice - 2,
                                          self.ORDER_TYPE_SELL_LIMIT)
            elif len(inDayOrder) == 0 and len(positionOrder) == 0:
                self.sendLimitOrder(sellPrice - 2, buyPrice,
                                    self.ORDER_TYPE_SELL_LIMIT)
            # 6点以前有挂单盈利单，继续挂单
            elif len(inDayOrder) != 0 and len(positionOrder) == 0:
                limitHour = stamp2datetime(inDayOrder[-1]["end_time"]).hour
                limitProfit = inDayOrder[-1]["profit"]
                if limitProfit > 0 and limitHour < 6 and timeHour > 6:
                    self.sendLimitOrder(sellPrice - 2, buyPrice,
                                        self.ORDER_TYPE_SELL_LIMIT)

    def sendLimitOrder(self, price, tp, t):
        """
        下挂单
        """
        limitSp = 0

        if t == self.ORDER_TYPE_BUY_LIMIT:
            limitSp = price - 4
        elif t == self.ORDER_TYPE_SELL_LIMIT:
            limitSp = price + 4

        result = self.control.createOrder(t,
                                          self.symble,
                                          limitPrice=price,
                                          priceSp=limitSp,
                                          priceTp=tp,
                                          remark=self.orderTag)
        if result is not None and result.retcode == self.TRADE_RETCODE_DONE:
            return True
        return False

    def deleteLastDayOrder(self):
        """
        删除前一天挂单
        """
        allOrder = self.getLimitOrderDetail(symbol=self.symble)
        self.removeOrder(allOrder)

        timeNow = datetime.datetime.now().day
        if self.lastDay != timeNow:
            self.lastDay = timeNow
            strategyList.clear()

            # 删除前一天挂单
            for item in allOrder:
                orderDay = stamp2datetime(local_stamp_2_gmt(
                    item.time_setup)).day
                if timeNow != orderDay:
                    self.closeOrder(item)

    def changeLimitOrder(self, lastPrice, currentPrice, orderType):
        """
        修改挂单价格
        是否存在该挂单，存在的话就修改
        """
        state = False
        for order in self.getLimitOrderDetail(symbol=self.symble,
                                              price=lastPrice,
                                              t=orderType):
            sp = 0
            if orderType == self.ORDER_TYPE_BUY_LIMIT:
                sp = currentPrice - 5
            elif orderType == self.ORDER_TYPE_SELL_LIMIT:
                sp = currentPrice + 5

            result = self.control.changeOrder(order,
                                              sp,
                                              0,
                                              price=currentPrice,
                                              t=2)
            state = True

        if state:
            prints("修改挂单完成")
        return state

    def removeOrder(self, limitList):
        """
        挂单成交时，删除另一挂单
        """

        if len(limitList) == 0:
            return

        closeLimit = False
        for item in self.getPositionsDetail(self.symble):
            if self.orderTag in item.comment:
                closeLimit = True

        if closeLimit:
            for child in limitList:
                self.closeOrder(child)
            prints("挂单已成交，删除其余挂单")
            sendMail("挂单已成交，删除其余挂单")

    def strategyChangeForRemoveOrder(self, deleteType):
        """
        主策略变化时，删除另一挂单
        """

        for item in self.getLimitOrderDetail(symbol=self.symble):
            if deleteType == "sell" and item.type == 3:
                self.closeOrder(item)
            elif deleteType == "buy" and item.type == 2:
                self.closeOrder(item)

    def move2Profit(self):
        """
        移动止盈
        """
        total = self.getPositionsDetail(self.symble)
        if total is None or len(total) == 0:
            return

        moveSp = False
        for item in total:
            priceOpen = item.price_open
            orderType = item.type
            profit = item.profit
            stopLoss = item.sl
            volume = item.volume
            ticket = item.ticket
            tp = item.tp

            slPrice = 0
            moveValue = 0.5
            profitSpace = volume * 100 * self.moveSpace  # 总盈利
            if profit > profitSpace:
                if profit / profitSpace >= 1:
                    moveValue = int(profit / profitSpace
                                    ) * self.moveSpace - self.moveProfit

                if orderType == 0:
                    slPrice = priceOpen + moveValue
                    if stopLoss != 0 and slPrice <= stopLoss:
                        return
                    self.control.changeOrder(item, slPrice, tp)
                    moveSp = True
                elif orderType == 1:
                    slPrice = priceOpen - moveValue
                    if stopLoss != 0 and slPrice >= stopLoss:
                        return
                    self.control.changeOrder(item, slPrice, tp)
                    moveSp = True

        if moveSp is True:
            prints("挂单_移动止损完成")
            sendMail("挂单_移动止损完成")
